JS 줌 앤 팬(Zoom and Pan) 구현하기(2)

April 29, 2024

JavaScript

지난 포스트에 이어 나머지 기능도 구현해보자.
이번엔 드래그와 드래그 시 경계를 벗어나지 않도록하는 bounding 기능을 구현해보겠다.

드래그 기능자체는 일반 Drag 기능과 크게 다르지 않았다.

우선 드래그 시작시 마우스 좌표와 target의 좌표를 저장할 변수를 생성하고
mousedown, mousemove, mouseup 각 이벤트에 대해 로직을 추가해준다.

//mouse
let startX, startY;
//target
let initialX = 0, initialY = 0;
let scale = 1; 
let tempX, tempY;
    viewer.addEventListener('mousedown', function (e) {
        e.preventDefault();
        startX = e.clientX;
        startY = e.clientY;
        isDragging = true;
    });

현재 마우스 위치에서 초기 마우스 위치를 빼서 이동한 거리 moveX, moveY를 계산한다.

이 값을 초기 위치에 더해 target이 이동할 새 위치newPosX, newPosY를 계산하고, 이를 transform 스타일을 통해 적용한다.

viewer.addEventListener('mousemove', function (e) {
    if (isDragging) {
        let moveX = e.clientX - startX;
        let moveY = e.clientY - startY;

        let newPosX = moveX + initialX
        let newPosY = moveY + initialY

        target.style.transform = `translateX(${newPosX}px) translateY(${newPosY}px) scale(${scale})`
        tempX = newPosX
        tempY = newPosY
    }
});

newPosX, newPosY 는 mousemove가 실행되는 동안은 tempX, tempY에 저장된다.

이후 mouseup 이벤트가 발생하면 tempX, tempY에 있는 값들을 initialX, initialY에 저장한다.

document.addEventListener('mouseup', function () {
    if (isDragging) {
        initialX = tempX;
        initialY = tempY;
        isDragging = false;
        target.style.cursor = 'grab';
    }
});

그럼 요렇게 드래그는 잘 동작한다!
근데 target의 모서리가가 viewer의 모서리 안쪽까지 드래그 되는것을 볼 수 있다.


그럼 이제 bounding을 적용해보자.

우선 updateLimits 라는 함수를 만든다.
함수가 실행되면 viewer의 모서리에서 target의 모서리까지 상하좌우로 움직일 수 있는 거리를 계산하고 객체로 변수에 그 값을 저장할것이다.

let dragLimits = {};

function updateLimits() {
    const vRect = viewer.getBoundingClientRect();
    const tRect = target.getBoundingClientRect();

    dragLimits = {
        minX: vRect.right - tRect.right,
        maxX: vRect.left - tRect.left,
        minY: vRect.bottom - tRect.bottom,
        maxY: vRect.top - tRect.top
    };
}

mousedown 이벤트가 발생하면 updatelimits함수를 실행시키고 매번 움직일 수 있는 거리를 계산한다.

그리고 mousemove 이벤트가 발생할 때 Math.max, Math.min을 활용해서 마우스 이동거리가 각 방향의 limit을 넘지 않도록 설정한다.

// mousemove
let moveX = e.clientX - startX;
let moveY = e.clientY - startY;

moveX = Math.max(dragLimits.minX, Math.min(dragLimits.maxX, moveX));
moveY = Math.max(dragLimits.minY, Math.min(dragLimits.maxY, moveY));

let newPosX = moveX + initialX
let newPosY = moveY + initialY

끝!

Profile picture

Written by yongho FrontEnd Developer